{
 "cells": [
  {
   "cell_type": "raw",
   "id": "500e8846-91c2-4716-9bd6-b9672c6daf78",
   "metadata": {},
   "source": [
    "---\n",
    "sidebar_position: 0\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14b94240",
   "metadata": {},
   "source": [
    "# Quickstart\n",
    "\n",
    "In this guide, we will go over the basic ways to create Chains and Agents that call Tools. Tools can be just about anything — APIs, functions, databases, etc. Tools allow us to extend the capabilities of a model beyond just outputting text/messages. The key to using models with tools is correctly prompting a model and parsing its response so that it chooses the right ools and provides the right inputs for them."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6b79a42-0349-42c6-9ce8-72220e838e8d",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "We'll need to install the following packages for this guide:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2274266-755a-4e90-b257-5180fb089af2",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install --upgrade --quiet langchain langchain-openai"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36a9c6fc-8264-462f-b8d7-9c7bbec22ef9",
   "metadata": {},
   "source": [
    "And set these environment variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "57a81b7a-4fd9-4f28-bc32-7b98b522e1b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import getpass\n",
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n",
    "\n",
    "# If you'd like to use LangSmith, uncomment the below\n",
    "# os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "# os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68946881",
   "metadata": {},
   "source": [
    "## Create a tool\n",
    "\n",
    "First, we need to create a tool to call. For this example, we will create a custom tool from a function. For more information on creating custom tools, please see [this guide](/docs/modules/agents/tools/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "90187d07",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.tools import tool\n",
    "\n",
    "\n",
    "@tool\n",
    "def multiply(first_int: int, second_int: int) -> int:\n",
    "    \"\"\"Multiply two integers together.\"\"\"\n",
    "    return first_int * second_int"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d7009e1a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "multiply\n",
      "multiply(first_int: int, second_int: int) -> int - Multiply two integers together.\n",
      "{'first_int': {'title': 'First Int', 'type': 'integer'}, 'second_int': {'title': 'Second Int', 'type': 'integer'}}\n"
     ]
    }
   ],
   "source": [
    "print(multiply.name)\n",
    "print(multiply.description)\n",
    "print(multiply.args)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "be77e780",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "multiply.invoke({\"first_int\": 4, \"second_int\": 5})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19ba4d63",
   "metadata": {},
   "source": [
    "## Chains\n",
    "\n",
    "If we know that we only need to use a tool a fixed number of times, we can create a chain for doing so. Let's create a simple chain that just multiplies user-specified numbers.\n",
    "\n",
    "![chain](../../../static/img/tool_chain.svg)\n",
    "\n",
    "### Function calling\n",
    "One of the most reliable ways to use tools with LLMs is with function calling APIs (also sometimes called tool calling or parallel function calling). This only works with models that explicitly support function calling, like OpenAI models.\n",
    "\n",
    "First we'll define our model and tools. We'll start with just a single tool, `multiply`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9bce8935-1465-45ac-8a93-314222c753c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai.chat_models import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(model=\"gpt-3.5-turbo-1106\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c22e6f0f-c5ad-4c0f-9514-e626704ea51c",
   "metadata": {},
   "source": [
    "Next we'll convert our LangChain Tool to an OpenAI format JSONSchema function, and bind this as the `tools` argument to be passed to all ChatOpenAI calls. Since we only have a single Tool and in this initial chain we want to make sure it's always used, we'll also specify `tool_choice`. See the [OpenAI chat API reference](https://platform.openai.com/docs/api-reference/chat/create#chat-create-tool_choice) for more on these parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2babd759-bccd-4d50-95ad-365a07347926",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'type': 'function',\n",
       "  'function': {'name': 'multiply',\n",
       "   'description': 'multiply(first_int: int, second_int: int) -> int - Multiply two integers together.',\n",
       "   'parameters': {'title': 'multiplySchemaSchema',\n",
       "    'type': 'object',\n",
       "    'properties': {'first_int': {'title': 'First Int', 'type': 'integer'},\n",
       "     'second_int': {'title': 'Second Int', 'type': 'integer'}},\n",
       "    'required': ['first_int', 'second_int']}}}]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.tools.convert_to_openai import (\n",
    "    format_tool_to_openai_tool,\n",
    ")\n",
    "\n",
    "formatted_tools = [format_tool_to_openai_tool(multiply)]\n",
    "formatted_tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3bfe2cdc-7d72-457c-a9a1-5fa1e0bcde55",
   "metadata": {},
   "outputs": [],
   "source": [
    "model_with_tools = model.bind(\n",
    "    tools=formatted_tools,\n",
    "    # We specify tool_choice to enforce that the 'multiply' function is called by the model.\n",
    "    tool_choice={\"type\": \"function\", \"function\": {\"name\": \"multiply\"}},\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9fa2ba14-9a97-4960-a6c7-422edecdaf4b",
   "metadata": {},
   "source": [
    "Now we'll compose out tool-calling model with a `JsonOutputToolsParser`, a built-in LangChain output parser that converts an OpenAI function-calling response to a list of `{\"type\": \"TOOL_NAME\", \"args\": {...}}` dicts with the tools to invoke and arguments to invoke them with."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5518aba4-c44d-4896-9b63-fc9d56c245df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'type': 'multiply', 'args': {'first_int': 4, 'second_int': 23}}]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.output_parsers import JsonOutputToolsParser\n",
    "\n",
    "chain = model_with_tools | JsonOutputToolsParser()\n",
    "chain.invoke(\"What's four times 23\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f712d8d-0314-4d3d-b563-378b72fd8bb5",
   "metadata": {},
   "source": [
    "Since we know we're always invoking the `multiply` tool, we can simplify our output a bit to return only the args for the `multiply` tool using the `JsonoutputKeyToolsParser`. To further simplify we'll specify `return_single=True`, so that instead of a list of tool invocations our output parser returns only the first tool invocation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "cfacfcdc-8a45-4c60-a175-7efe9534f83e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'first_int': 4, 'second_int': 23}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.output_parsers import JsonOutputKeyToolsParser\n",
    "\n",
    "chain = model_with_tools | JsonOutputKeyToolsParser(\n",
    "    key_name=\"multiply\", return_single=True\n",
    ")\n",
    "chain.invoke(\"What's four times 23\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ba1764d-0272-4f98-adcf-b48cb2c0a315",
   "metadata": {},
   "source": [
    "### Invoking the tool\n",
    "\n",
    "Great! We're able to generate tool invocations. But what if we want to actually call the tool? To do that we just need to pass them to the tool:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "4f5325ca-e5dc-4d1a-ba36-b085a029c90a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "92"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from operator import itemgetter\n",
    "\n",
    "# Note: the `.map()` at the end of `multiply` allows us to pass in a list of `multiply` arguments instead of a single one.\n",
    "chain = (\n",
    "    model_with_tools\n",
    "    | JsonOutputKeyToolsParser(key_name=\"multiply\", return_single=True)\n",
    "    | multiply\n",
    ")\n",
    "chain.invoke(\"What's four times 23\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0521d3d5",
   "metadata": {},
   "source": [
    "## Agents\n",
    "\n",
    "Chains are great when we know the specific sequence of tool usage needed for any user input. But for certain use cases, how many times we use tools depends on the input. In these cases, we want to let the model itself decide how many times to use tools and in what order. [Agents](/docs/modules/agents/) let us do just this.\n",
    "\n",
    "LangChain comes with a number of built-in agents that are optimized for different use cases. Read about all the [agent types here](/docs/modules/agents/agent_types/).\n",
    "\n",
    "As an example, let's try out the OpenAI tools agent, which makes use of the new OpenAI tool-calling API (this is only available in the latest OpenAI models, and differs from function-calling in that the model can return multiple function invocations at once)\n",
    "\n",
    "![agent](../../../static/img/tool_agent.svg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "21723cf4-9421-4a8d-92a6-eeeb8f4367f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import hub\n",
    "from langchain.agents import AgentExecutor, create_openai_tools_agent\n",
    "from langchain_openai import ChatOpenAI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "6be83879-9da3-4dd9-b147-a79f76affd7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')),\n",
       " MessagesPlaceholder(variable_name='chat_history', optional=True),\n",
       " HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')),\n",
       " MessagesPlaceholder(variable_name='agent_scratchpad')]"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/openai-tools-agent\")\n",
    "prompt.messages"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "616f9714-5b18-4eed-b88a-d38e4cb1de99",
   "metadata": {},
   "source": [
    "Agents are also great because they make it easy to use multiple tools. To learn how to build Chains that use multiple tools, check out the [Chains with multiple tools](/docs/use_cases/tool_use/multiple_tools) page."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "95c86d32-ee45-4c87-a28c-14eff19b49e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def add(first_int: int, second_int: int) -> int:\n",
    "    \"Add two integers.\"\n",
    "    return first_int + second_int\n",
    "\n",
    "\n",
    "@tool\n",
    "def exponentiate(base: int, exponent: int) -> int:\n",
    "    \"Exponentiate the base to the exponent power.\"\n",
    "    return base**exponent\n",
    "\n",
    "\n",
    "tools = [multiply, add, exponentiate]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "17b09ac6-c9b7-4340-a8a0-3d3061f7888c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Choose the LLM that will drive the agent\n",
    "# Only certain models support this\n",
    "model = ChatOpenAI(model=\"gpt-3.5-turbo-1106\", temperature=0)\n",
    "\n",
    "# Construct the OpenAI Tools agent\n",
    "agent = create_openai_tools_agent(model, tools, prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "id": "675091d2-cac9-45c4-a5d7-b760ee6c1986",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6099ab6-2fa6-452d-b73c-7fb65daab451",
   "metadata": {},
   "source": [
    "With an agent, we can ask questions that require arbitrarily-many uses of our tools:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "f7dbb240-809e-4e41-8f63-1a4636e8e26d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `exponentiate` with `{'base': 3, 'exponent': 5}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[38;5;200m\u001b[1;3m243\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add` with `{'first_int': 12, 'second_int': 3}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m15\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `multiply` with `{'first_int': 243, 'second_int': 15}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3m3645\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `exponentiate` with `{'base': 3645, 'exponent': 2}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[38;5;200m\u001b[1;3m13286025\u001b[0m\u001b[32;1m\u001b[1;3mThe result of raising 3 to the fifth power and multiplying that by the sum of twelve and three, then squaring the whole result is 13,286,025.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'Take 3 to the fifth power and multiply that by the sum of twelve and three, then square the whole result',\n",
       " 'output': 'The result of raising 3 to the fifth power and multiplying that by the sum of twelve and three, then squaring the whole result is 13,286,025.'}"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke(\n",
    "    {\n",
    "        \"input\": \"Take 3 to the fifth power and multiply that by the sum of twelve and three, then square the whole result\"\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0e4b7f4-58ce-4ca0-a986-d05a436a7ccf",
   "metadata": {},
   "source": [
    "## Next steps\n",
    "\n",
    "Here we've gone over the basic ways to use Tools with Chains and Agents. We recommend the following sections to explore next:\n",
    "\n",
    "- [Agents](/docs/modules/agents/): Everything related to Agents.\n",
    "- [Choosing between multiple tools](/docs/use_cases/tool_use/multiple_tools): How to make tool chains that select from multiple tools.\n",
    "- [Prompting for tool use](/docs/use_cases/tool_use/prompting): How to make tool chains that prompt models directly, without using function-calling APIs.\n",
    "- [Parallel tool use](/docs/use_cases/tool_use/parallel): How to make tool chains that invoke multiple tools at once."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "poetry-venv",
   "language": "python",
   "name": "poetry-venv"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
